home *** CD-ROM | disk | FTP | other *** search
/ EuroCD 3 / EuroCD 3.iso / Games / Doom / ADoom-0.8 / ADoom_src / d_main.c < prev    next >
C/C++ Source or Header  |  1998-06-24  |  27KB  |  1,201 lines

  1. // Emacs style mode select   -*- C++ -*- 
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. //    DOOM main program (D_DoomMain) and game loop (D_DoomLoop),
  21. //    plus functions to determine game mode (shareware, registered),
  22. //    parse command line parameters, configure game parameters (turbo),
  23. //    and call the startup functions.
  24. //
  25. //-----------------------------------------------------------------------------
  26.  
  27.  
  28. static const char rcsid[] = "$Id: d_main.c,v 1.8 1997/02/03 22:45:09 b1 Exp $";
  29.  
  30. #define    BGCOLOR        7
  31. #define    FGCOLOR        8
  32.  
  33.  
  34. #ifdef NORMALUNIX
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <unistd.h>
  38. #include <sys/types.h>
  39. #include <sys/stat.h>
  40. #include <fcntl.h>
  41. #endif
  42.  
  43.  
  44. #include "doomdef.h"
  45. #include "doomstat.h"
  46.  
  47. #include "dstrings.h"
  48. #include "sounds.h"
  49.  
  50.  
  51. #include "z_zone.h"
  52. #include "w_wad.h"
  53. #include "s_sound.h"
  54. #include "v_video.h"
  55.  
  56. #include "f_finale.h"
  57. #include "f_wipe.h"
  58.  
  59. #include "m_argv.h"
  60. #include "m_misc.h"
  61. #include "m_menu.h"
  62.  
  63. #include "i_system.h"
  64. #include "i_sound.h"
  65. #include "i_video.h"
  66.  
  67. #include "g_game.h"
  68.  
  69. #include "hu_stuff.h"
  70. #include "wi_stuff.h"
  71. #include "st_stuff.h"
  72. #include "am_map.h"
  73.  
  74. #include "p_setup.h"
  75. #include "r_local.h"
  76.  
  77.  
  78. #include "d_main.h"
  79.  
  80. //
  81. // D-DoomLoop()
  82. // Not a globally visible function,
  83. //  just included for source reference,
  84. //  called by D_DoomMain, never exits.
  85. // Manages timing and IO,
  86. //  calls all ?_Responder, ?_Ticker, and ?_Drawer,
  87. //  calls I_GetTime, I_StartFrame, and I_StartTic
  88. //
  89. void D_DoomLoop (void);
  90.  
  91.  
  92. char*        wadfiles[MAXWADFILES];
  93.  
  94.  
  95. boolean        devparm;    // started game with -devparm
  96. boolean         nomonsters;    // checkparm of -nomonsters
  97. boolean         respawnparm;    // checkparm of -respawn
  98. boolean         fastparm;    // checkparm of -fast
  99. boolean         rotatemap;      // checkparm of -rotatemap
  100. boolean         maponhu;        // checkparm of -maponhu
  101.  
  102. boolean         drone;
  103.  
  104. boolean        singletics = false; // debug flag to cancel adaptiveness
  105.  
  106.  
  107.  
  108. //extern int soundVolume;
  109. //extern  int    sfxVolume;
  110. //extern  int    musicVolume;
  111.  
  112. extern  boolean    inhelpscreens;
  113. extern  boolean maponhu;
  114.  
  115. skill_t        startskill;
  116. int             startepisode;
  117. int        startmap;
  118. boolean        autostart;
  119.  
  120. FILE*        debugfile;
  121.  
  122. boolean        advancedemo;
  123.  
  124.  
  125.  
  126.  
  127. char        wadfile[1024];        // primary wad file
  128. char        mapdir[1024];           // directory of development maps
  129. char        basedefault[1024];      // default file
  130.  
  131.  
  132. void D_CheckNetGame (void);
  133. void D_ProcessEvents (void);
  134. void G_BuildTiccmd (ticcmd_t* cmd);
  135. void D_DoAdvanceDemo (void);
  136.  
  137.  
  138. //
  139. // EVENT HANDLING
  140. //
  141. // Events are asynchronous inputs generally generated by the game user.
  142. // Events can be discarded if no responder claims them
  143. //
  144. event_t         events[MAXEVENTS];
  145. int             eventhead;
  146. int         eventtail;
  147.  
  148.  
  149. //
  150. // D_PostEvent
  151. // Called by the I/O functions when input is detected
  152. //
  153. void D_PostEvent (event_t* ev)
  154. {
  155.     events[eventhead] = *ev;
  156.     eventhead = (++eventhead)&(MAXEVENTS-1);
  157. }
  158.  
  159.  
  160. //
  161. // D_ProcessEvents
  162. // Send all the events of the given timestamp down the responder chain
  163. //
  164. void D_ProcessEvents (void)
  165. {
  166.     event_t*    ev;
  167.     
  168.     // IF STORE DEMO, DO NOT ACCEPT INPUT
  169.     if ( ( gamemode == commercial )
  170.      && (W_CheckNumForName("map01")<0) )
  171.       return;
  172.     
  173.     for ( ; eventtail != eventhead ; eventtail = (++eventtail)&(MAXEVENTS-1) )
  174.     {
  175.     ev = &events[eventtail];
  176.     if (M_Responder (ev))
  177.         continue;               // menu ate the event
  178.     G_Responder (ev);
  179.     }
  180. }
  181.  
  182.  
  183.  
  184.  
  185. //
  186. // D_Display
  187. //  draw current display, possibly wiping it from the previous
  188. //
  189.  
  190. // wipegamestate can be set to -1 to force a wipe on the next draw
  191. gamestate_t     wipegamestate = GS_DEMOSCREEN;
  192. extern  boolean setsizeneeded;
  193. extern  int             showMessages;
  194. void R_ExecuteSetViewSize (void);
  195.  
  196. void D_Display (void)
  197. {
  198.     static  boolean        viewactivestate = false;
  199.     static  boolean        menuactivestate = false;
  200.     static  boolean        inhelpscreensstate = false;
  201.     static  boolean        fullscreen = false;
  202.     static  gamestate_t        oldgamestate = -1;
  203.     static  int            borderdrawcount;
  204.     int                nowtime;
  205.     int                tics;
  206.     int                wipestart;
  207.     int                y;
  208.     boolean            done;
  209.     boolean            wipe;
  210.     boolean            redrawsbar;
  211.  
  212.     if (nodrawers)
  213.     return;                    // for comparative timing / profiling
  214.         
  215.     redrawsbar = false;
  216.     
  217.     // start updating gfx in screens[0] here
  218.     I_StartUpdate ();
  219.  
  220.     // change the view size if needed
  221.     if (setsizeneeded)
  222.     {
  223.     R_ExecuteSetViewSize ();
  224.     oldgamestate = -1;                      // force background redraw
  225.     borderdrawcount = 3;
  226.     }
  227.  
  228.     // save the current screen if about to wipe
  229.     if (gamestate != wipegamestate)
  230.     {
  231.     wipe = true;
  232.     wipe_StartScreen(0, 0, SCREENWIDTH, SCREENHEIGHT);
  233.     }
  234.     else
  235.     wipe = false;
  236.  
  237.     if (gamestate == GS_LEVEL && gametic)
  238.     HU_Erase();
  239.     
  240.     // do buffered drawing
  241.     switch (gamestate)
  242.     {
  243.       case GS_LEVEL:
  244.     if (!gametic)
  245.         break;
  246.         /* Map On Headup Patch - CDE - 97'
  247.     if (automapactive)
  248.         AM_Drawer ();
  249.         */
  250.     if (wipe || (viewheight != 200 && fullscreen) )
  251.         redrawsbar = true;
  252.     if (inhelpscreensstate && !inhelpscreens)
  253.         redrawsbar = true;              // just put away the help screen
  254.     ST_Drawer (viewheight == 200, redrawsbar );
  255.     fullscreen = viewheight == 200;
  256.     break;
  257.  
  258.       case GS_INTERMISSION:
  259.     WI_Drawer ();
  260.     break;
  261.  
  262.       case GS_FINALE:
  263.     F_Drawer ();
  264.     break;
  265.  
  266.       case GS_DEMOSCREEN:
  267.     D_PageDrawer ();
  268.     break;
  269.     }
  270.     
  271.     // draw buffered stuff to screen
  272.     I_UpdateNoBlit ();
  273.     
  274.     // draw the view directly
  275.     if (gamestate == GS_LEVEL && (!automapactive || maponhu) && gametic)
  276.     R_RenderPlayerView (&players[displayplayer]);
  277.  
  278.     /* Map On HeadUp Patch - CDE 98' */
  279.     if (gamestate == GS_LEVEL && automapactive)
  280.         AM_Drawer ();
  281.  
  282.     if (gamestate == GS_LEVEL && gametic)
  283.     HU_Drawer ();
  284.     
  285.     // clean up border stuff
  286.     if (gamestate != oldgamestate && gamestate != GS_LEVEL)
  287.     I_SetPalette (W_CacheLumpName ("PLAYPAL",PU_CACHE));
  288.  
  289.     // see if the border needs to be initially drawn
  290.     if (gamestate == GS_LEVEL && oldgamestate != GS_LEVEL)
  291.     {
  292.     viewactivestate = false;        // view was not active
  293.     R_FillBackScreen ();    // draw the pattern into the back screen
  294.     }
  295.  
  296.     // see if the border needs to be updated to the screen
  297.     if (gamestate == GS_LEVEL && !automapactive && scaledviewwidth != 320)
  298.     {
  299.     if (menuactive || menuactivestate || !viewactivestate)
  300.         borderdrawcount = 3;
  301.     if (borderdrawcount)
  302.     {
  303.         R_DrawViewBorder ();    // erase old menu stuff
  304.         borderdrawcount--;
  305.     }
  306.  
  307.     }
  308.  
  309.     menuactivestate = menuactive;
  310.     viewactivestate = viewactive;
  311.     inhelpscreensstate = inhelpscreens;
  312.     oldgamestate = wipegamestate = gamestate;
  313.     
  314.     // draw pause pic
  315.     if (paused)
  316.     {
  317.     if (automapactive)
  318.         y = 4;
  319.     else
  320.         y = viewwindowy+4;
  321.     V_DrawPatchDirect(viewwindowx+(scaledviewwidth-68)/2,
  322.               y,0,W_CacheLumpName ("M_PAUSE", PU_CACHE));
  323.     }
  324.  
  325.  
  326.     // menus go directly to the screen
  327.     M_Drawer ();          // menu is drawn even on top of everything
  328.     NetUpdate ();         // send out any new accumulation
  329.  
  330.  
  331.     // normal update
  332.     if (!wipe)
  333.     {
  334.     I_FinishUpdate ();              // page flip or blit buffer
  335.     return;
  336.     }
  337.     
  338.     // wipe update
  339.     wipe_EndScreen(0, 0, SCREENWIDTH, SCREENHEIGHT);
  340.  
  341.     wipestart = I_GetTime () - 1;
  342.  
  343.     do
  344.     {
  345.     do
  346.     {
  347.         nowtime = I_GetTime ();
  348.         tics = nowtime - wipestart;
  349.     } while (!tics);
  350.     wipestart = nowtime;
  351.     done = wipe_ScreenWipe(wipe_Melt
  352.                    , 0, 0, SCREENWIDTH, SCREENHEIGHT, tics);
  353.         I_StartUpdate ();
  354.     I_UpdateNoBlit ();
  355.     M_Drawer ();                            // menu is drawn even on top of wipes
  356.     I_FinishUpdate ();                      // page flip or blit buffer
  357.     } while (!done);
  358. }
  359.  
  360.  
  361.  
  362. //
  363. //  D_DoomLoop
  364. //
  365. extern  boolean         demorecording;
  366.  
  367. void D_DoomLoop (void)
  368. {
  369.     if (demorecording)
  370.     G_BeginRecording ();
  371.         
  372.     if (M_CheckParm ("-debugfile"))
  373.     {
  374.     char    filename[20];
  375.     sprintf (filename,"debug%i.txt",consoleplayer);
  376.     printf ("debug output to: %s\n",filename);
  377.     debugfile = fopen (filename,"w");
  378.     }
  379.     
  380.     I_InitGraphics ();
  381.  
  382.     while (1)
  383.     {
  384.     // frame syncronous IO operations
  385.     I_StartFrame ();                
  386.     
  387.     // process one or more tics
  388.     if (singletics)
  389.     {
  390.         I_StartTic ();
  391.         D_ProcessEvents ();
  392.         G_BuildTiccmd (&netcmds[consoleplayer][maketic%BACKUPTICS]);
  393.         if (advancedemo)
  394.         D_DoAdvanceDemo ();
  395.         M_Ticker ();
  396.         G_Ticker ();
  397.         gametic++;
  398.         maketic++;
  399.     }
  400.     else
  401.     {
  402.         TryRunTics (); // will run at least one tic
  403.     }
  404.         
  405.     S_UpdateSounds (players[consoleplayer].mo);// move positional sounds
  406.  
  407.     // Update display, next frame, with current state.
  408.     D_Display ();
  409.  
  410. #if 0
  411. #ifndef SNDSERV
  412.     // Sound mixing for the buffer is snychronous.
  413.     I_UpdateSound();
  414. #endif    
  415.     // Synchronous sound output is explicitly called.
  416. #ifndef SNDINTR
  417.     // Update sound output.
  418.     I_SubmitSound();
  419. #endif
  420. #endif
  421.     }
  422. }
  423.  
  424.  
  425.  
  426. //
  427. //  DEMO LOOP
  428. //
  429. int             demosequence;
  430. int             pagetic;
  431. char                    *pagename;
  432.  
  433.  
  434. //
  435. // D_PageTicker
  436. // Handles timing for warped projection
  437. //
  438. void D_PageTicker (void)
  439. {
  440.     if (--pagetic < 0)
  441.     D_AdvanceDemo ();
  442. }
  443.  
  444.  
  445.  
  446. //
  447. // D_PageDrawer
  448. //
  449. void D_PageDrawer (void)
  450. {
  451.     V_DrawPatch (0,0, 0, W_CacheLumpName(pagename, PU_CACHE));
  452. }
  453.  
  454.  
  455. //
  456. // D_AdvanceDemo
  457. // Called after each demo or intro demosequence finishes
  458. //
  459. void D_AdvanceDemo (void)
  460. {
  461.     advancedemo = true;
  462. }
  463.  
  464.  
  465. //
  466. // This cycles through the demo sequences.
  467. // FIXME - version dependend demo numbers?
  468. //
  469.  void D_DoAdvanceDemo (void)
  470. {
  471.     players[consoleplayer].playerstate = PST_LIVE;  // not reborn
  472.     advancedemo = false;
  473.     usergame = false;               // no save / end game here
  474.     paused = false;
  475.     gameaction = ga_nothing;
  476.  
  477.     if ( gamemode == retail )
  478.       demosequence = (demosequence+1)%7;
  479.     else
  480.       demosequence = (demosequence+1)%6;
  481.     
  482.     switch (demosequence)
  483.     {
  484.       case 0:
  485.     if ( gamemode == commercial )
  486.         pagetic = 35 * 11;
  487.     else
  488.         pagetic = 170;
  489.     gamestate = GS_DEMOSCREEN;
  490.     pagename = "TITLEPIC";
  491.     if ( gamemode == commercial )
  492.       S_StartMusic(mus_dm2ttl);
  493.     else
  494.       S_StartMusic (mus_intro);
  495.     break;
  496.       case 1:
  497.     G_DeferedPlayDemo ("demo1");
  498.     break;
  499.       case 2:
  500.     pagetic = 200;
  501.     gamestate = GS_DEMOSCREEN;
  502.     pagename = "CREDIT";
  503.     break;
  504.       case 3:
  505.     G_DeferedPlayDemo ("demo2");
  506.     break;
  507.       case 4:
  508.     gamestate = GS_DEMOSCREEN;
  509.     if ( gamemode == commercial)
  510.     {
  511.         pagetic = 35 * 11;
  512.         pagename = "TITLEPIC";
  513.         S_StartMusic(mus_dm2ttl);
  514.     }
  515.     else
  516.     {
  517.         pagetic = 200;
  518.  
  519.         if ( gamemode == retail )
  520.           pagename = "CREDIT";
  521.         else
  522.           pagename = "HELP2";
  523.     }
  524.     break;
  525.       case 5:
  526.     G_DeferedPlayDemo ("demo3");
  527.     break;
  528.         // THE DEFINITIVE DOOM Special Edition demo
  529.       case 6:
  530.     G_DeferedPlayDemo ("demo4");
  531.     break;
  532.     }
  533. }
  534.  
  535.  
  536.  
  537. //
  538. // D_StartTitle
  539. //
  540. void D_StartTitle (void)
  541. {
  542.     gameaction = ga_nothing;
  543.     demosequence = -1;
  544.     D_AdvanceDemo ();
  545. }
  546.  
  547.  
  548.  
  549.  
  550. //      print title for every printed line
  551. char            title[128];
  552.  
  553.  
  554.  
  555. //
  556. // D_AddFile
  557. //
  558. void D_AddFile (char *file)
  559. {
  560.     int     numwadfiles;
  561.     char    *newfile;
  562.     
  563.     for (numwadfiles = 0 ; wadfiles[numwadfiles] ; numwadfiles++)
  564.     ;
  565.  
  566.     newfile = malloc (strlen(file)+1);
  567.     strcpy (newfile, file);
  568.     
  569.     wadfiles[numwadfiles] = newfile;
  570. }
  571.  
  572. //
  573. // IdentifyVersion
  574. // Checks availability of IWAD files by name,
  575. // to determine whether registered/commercial features
  576. // should be executed (notably loading PWAD's).
  577. //
  578. void IdentifyVersion (void)
  579. {
  580.  
  581.     char*    doom1wad;
  582.     char*    doomwad;
  583.     char*    doomuwad;
  584.     char*    doom2wad;
  585.  
  586.     char*    doom2fwad;
  587.     char*    plutoniawad;
  588.     char*    tntwad;
  589.  
  590. #ifdef NORMALUNIX
  591.     static char home[256];
  592.     char *doomwaddir;
  593.     doomwaddir = getenv("DOOMWADDIR");
  594.     if (!doomwaddir)
  595.     doomwaddir = "PROGDIR:";
  596.  
  597.     // Commercial.
  598.     doom2wad = malloc(strlen(doomwaddir)+1+9+1);
  599.     sprintf(doom2wad, "%sdoom2.wad", doomwaddir);
  600.  
  601.     // Retail.
  602.     doomuwad = malloc(strlen(doomwaddir)+1+8+1);
  603.     sprintf(doomuwad, "%sdoomu.wad", doomwaddir);
  604.     
  605.     // Registered.
  606.     doomwad = malloc(strlen(doomwaddir)+1+8+1);
  607.     sprintf(doomwad, "%sdoom.wad", doomwaddir);
  608.     
  609.     // Shareware.
  610.     doom1wad = malloc(strlen(doomwaddir)+1+9+1);
  611.     sprintf(doom1wad, "%sdoom1.wad", doomwaddir);
  612.  
  613.      // Bug, dear Shawn.
  614.     // Insufficient malloc, caused spurious realloc errors.
  615.     plutoniawad = malloc(strlen(doomwaddir)+1+/*9*/12+1);
  616.     sprintf(plutoniawad, "%splutonia.wad", doomwaddir);
  617.  
  618.     tntwad = malloc(strlen(doomwaddir)+1+9+1);
  619.     sprintf(tntwad, "%stnt.wad", doomwaddir);
  620.  
  621.  
  622.     // French stuff.
  623.     doom2fwad = malloc(strlen(doomwaddir)+1+10+1);
  624.     sprintf(doom2fwad, "%sdoom2f.wad", doomwaddir);
  625.  
  626. #ifdef __SASC
  627.     if (getenv ("HOME") != NULL) {
  628.       strcpy (home, getenv("HOME"));
  629.       if (home[strlen(home)-1] != '/' && home[strlen(home)-1] != ':')
  630.         strcat (home, "/");
  631.     } else
  632.       home[0] = '\0';
  633. #else
  634.     home = getenv ("HOME");
  635.     if (!home)
  636.       I_Error("Please set $HOME to your home directory");
  637. #endif
  638.     sprintf(basedefault, "%s.doomrc", home);
  639. #endif
  640.  
  641.     if (M_CheckParm ("-shdev"))
  642.     {
  643.     gamemode = shareware;
  644.     devparm = true;
  645.     D_AddFile (DEVDATA"doom1.wad");
  646.     D_AddFile (DEVMAPS"data_se/texture1.lmp");
  647.     D_AddFile (DEVMAPS"data_se/pnames.lmp");
  648.     strcpy (basedefault,DEVDATA"default.cfg");
  649.     return;
  650.     }
  651.  
  652.     if (M_CheckParm ("-regdev"))
  653.     {
  654.     gamemode = registered;
  655.     devparm = true;
  656.     D_AddFile (DEVDATA"doom.wad");
  657.     D_AddFile (DEVMAPS"data_se/texture1.lmp");
  658.     D_AddFile (DEVMAPS"data_se/texture2.lmp");
  659.     D_AddFile (DEVMAPS"data_se/pnames.lmp");
  660.     strcpy (basedefault,DEVDATA"default.cfg");
  661.     return;
  662.     }
  663.  
  664.     if (M_CheckParm ("-comdev"))
  665.     {
  666.     gamemode = commercial;
  667.     devparm = true;
  668.     /* I don't bother
  669.     if(plutonia)
  670.         D_AddFile (DEVDATA"plutonia.wad");
  671.     else if(tnt)
  672.         D_AddFile (DEVDATA"tnt.wad");
  673.     else*/
  674.         D_AddFile (DEVDATA"doom2.wad");
  675.         
  676.     D_AddFile (DEVMAPS"cdata/texture1.lmp");
  677.     D_AddFile (DEVMAPS"cdata/pnames.lmp");
  678.     strcpy (basedefault,DEVDATA"default.cfg");
  679.     return;
  680.     }
  681.  
  682.     if ( !access (doom2fwad,R_OK) )
  683.     {
  684.     gamemode = commercial;
  685.     // C'est ridicule!
  686.     // Let's handle languages in config files, okay?
  687.     language = french;
  688.     printf("French version\n");
  689.     D_AddFile (doom2fwad);
  690.     return;
  691.     }
  692.  
  693.     if ( !access (doom2wad,R_OK) )
  694.     {
  695.     gamemode = commercial;
  696.     D_AddFile (doom2wad);
  697.     return;
  698.     }
  699.  
  700.     if ( !access (plutoniawad, R_OK ) )
  701.     {
  702.       gamemode = commercial;
  703.       D_AddFile (plutoniawad);
  704.       return;
  705.     }
  706.  
  707.     if ( !access ( tntwad, R_OK ) )
  708.     {
  709.       gamemode = commercial;
  710.       D_AddFile (tntwad);
  711.       return;
  712.     }
  713.  
  714.     if ( !access (doomuwad,R_OK) )
  715.     {
  716.       gamemode = retail;
  717.       D_AddFile (doomuwad);
  718.       return;
  719.     }
  720.  
  721.     if ( !access (doomwad,R_OK) )
  722.     {
  723.       gamemode = registered;
  724.       D_AddFile (doomwad);
  725.       return;
  726.     }
  727.  
  728.     if ( !access (doom1wad,R_OK) )
  729.     {
  730.       gamemode = shareware;
  731.       D_AddFile (doom1wad);
  732.       return;
  733.     }
  734.  
  735.     printf("Game mode indeterminate.\n");
  736.     gamemode = indetermined;
  737.  
  738.     // We don't abort. Let's see what the PWAD contains.
  739.     //exit(1);
  740.     //I_Error ("Game mode indeterminate\n");
  741. }
  742.  
  743. //
  744. // Find a Response File
  745. //
  746. void FindResponseFile (void)
  747. {
  748.     int             i;
  749.     
  750.     for (i = 1;i < myargc;i++)
  751.     if (myargv[i][0] == '@')
  752.     {
  753.         FILE *          handle;
  754.         int             size;
  755.         int             k;
  756.         int             index;
  757.         int             indexinfile;
  758.         char    *infile;
  759.         char    *file;
  760.         char    *moreargs[20];
  761.         char    *firstargv;
  762.             
  763.         // READ THE RESPONSE FILE INTO MEMORY
  764.         handle = fopen (&myargv[i][1],"rb");
  765.         if (!handle)
  766.         {
  767.         printf ("\nNo such response file!");
  768.         exit(1);
  769.         }
  770.         printf("Found response file %s!\n",&myargv[i][1]);
  771.         fseek (handle,0,SEEK_END);
  772.         size = ftell(handle);
  773.         fseek (handle,0,SEEK_SET);
  774.         file = malloc (size);
  775.         fread (file,size,1,handle);
  776.         fclose (handle);
  777.             
  778.         // KEEP ALL CMDLINE ARGS FOLLOWING @RESPONSEFILE ARG
  779.         for (index = 0,k = i+1; k < myargc; k++)
  780.         moreargs[index++] = myargv[k];
  781.             
  782.         firstargv = myargv[0];
  783.         myargv = malloc(sizeof(char *)*MAXARGVS);
  784.         memset(myargv,0,sizeof(char *)*MAXARGVS);
  785.         myargv[0] = firstargv;
  786.             
  787.         infile = file;
  788.         indexinfile = k = 0;
  789.         indexinfile++;  // SKIP PAST ARGV[0] (KEEP IT)
  790.         do
  791.         {
  792.         myargv[indexinfile++] = infile+k;
  793.         while(k < size &&
  794.               ((*(infile+k)>= ' '+1) && (*(infile+k)<='z')))
  795.             k++;
  796.         *(infile+k) = 0;
  797.         while(k < size &&
  798.               ((*(infile+k)<= ' ') || (*(infile+k)>'z')))
  799.             k++;
  800.         } while(k < size);
  801.             
  802.         for (k = 0;k < index;k++)
  803.         myargv[indexinfile++] = moreargs[k];
  804.         myargc = indexinfile;
  805.     
  806.         // DISPLAY ARGS
  807.         printf("%d command-line args:\n",myargc);
  808.         for (k=1;k<myargc;k++)
  809.         printf("%s\n",myargv[k]);
  810.  
  811.         break;
  812.     }
  813. }
  814.  
  815.  
  816. //
  817. // D_DoomMain
  818. //
  819. void D_DoomMain (void)
  820. {
  821.     int             p;
  822.     char                    file[256];
  823.  
  824.     FindResponseFile ();
  825.     
  826.     IdentifyVersion ();
  827.     
  828.     setbuf (stdout, NULL);
  829.     modifiedgame = false;
  830.     
  831.     nomonsters = M_CheckParm ("-nomonsters");
  832.     respawnparm = M_CheckParm ("-respawn");
  833.     fastparm = M_CheckParm ("-fast");
  834.     rotatemap = M_CheckParm ("-rotatemap");
  835.     devparm = M_CheckParm ("-devparm");
  836.     maponhu = M_CheckParm ("-maponhu");
  837.     if (M_CheckParm ("-altdeath"))
  838.     deathmatch = 2;
  839.     else if (M_CheckParm ("-deathmatch"))
  840.     deathmatch = 1;
  841.  
  842.     switch ( gamemode )
  843.     {
  844.       case retail:
  845.     sprintf (title,
  846.          "                         "
  847.          "The Ultimate DOOM Startup v%i.%i"
  848.          "                           ",
  849.          VERSION/100,VERSION%100);
  850.     break;
  851.       case shareware:
  852.     sprintf (title,
  853.          "                            "
  854.          "DOOM Shareware Startup v%i.%i"
  855.          "                           ",
  856.          VERSION/100,VERSION%100);
  857.     break;
  858.       case registered:
  859.     sprintf (title,
  860.          "                            "
  861.          "DOOM Registered Startup v%i.%i"
  862.          "                           ",
  863.          VERSION/100,VERSION%100);
  864.     break;
  865.       case commercial:
  866.     sprintf (title,
  867.          "                         "
  868.          "DOOM 2: Hell on Earth v%i.%i"
  869.          "                           ",
  870.          VERSION/100,VERSION%100);
  871.     break;
  872. /*FIXME
  873.        case pack_plut:
  874.     sprintf (title,
  875.          "                   "
  876.          "DOOM 2: Plutonia Experiment v%i.%i"
  877.          "                           ",
  878.          VERSION/100,VERSION%100);
  879.     break;
  880.       case pack_tnt:
  881.     sprintf (title,
  882.          "                     "
  883.          "DOOM 2: TNT - Evilution v%i.%i"
  884.          "                           ",
  885.          VERSION/100,VERSION%100);
  886.     break;
  887. */
  888.       default:
  889.     sprintf (title,
  890.          "                     "
  891.          "Public DOOM - v%i.%i"
  892.          "                           ",
  893.          VERSION/100,VERSION%100);
  894.     break;
  895.     }
  896.     
  897.     printf ("%s\n",title);
  898.  
  899.     if (devparm)
  900.     printf(D_DEVSTR);
  901.     
  902.     if (M_CheckParm("-cdrom"))
  903.     {
  904.     printf(D_CDROM);
  905. #ifdef __SASC
  906.     mkdir("c:\\doomdata");
  907. #else
  908.     mkdir("c:\\doomdata",0);
  909. #endif
  910.     strcpy (basedefault,"c:/doomdata/default.cfg");
  911.     }    
  912.     
  913.     // turbo option
  914.     if ( (p=M_CheckParm ("-turbo")) )
  915.     {
  916.     int     scale = 200;
  917.     extern int forwardmove[2];
  918.     extern int sidemove[2];
  919.     
  920.     if (p<myargc-1)
  921.         scale = atoi (myargv[p+1]);
  922.     if (scale < 10)
  923.         scale = 10;
  924.     if (scale > 400)
  925.         scale = 400;
  926.     printf ("turbo scale: %i%%\n",scale);
  927.     forwardmove[0] = forwardmove[0]*scale/100;
  928.     forwardmove[1] = forwardmove[1]*scale/100;
  929.     sidemove[0] = sidemove[0]*scale/100;
  930.     sidemove[1] = sidemove[1]*scale/100;
  931.     }
  932.     
  933.     // add any files specified on the command line with -file wadfile
  934.     // to the wad list
  935.     //
  936.     // convenience hack to allow -wart e m to add a wad file
  937.     // prepend a tilde to the filename so wadfile will be reloadable
  938.     p = M_CheckParm ("-wart");
  939.     if (p)
  940.     {
  941.     myargv[p][4] = 'p';     // big hack, change to -warp
  942.  
  943.     // Map name handling.
  944.     switch (gamemode )
  945.     {
  946.       case shareware:
  947.       case retail:
  948.       case registered:
  949.         sprintf (file,"~"DEVMAPS"E%cM%c.wad",
  950.              myargv[p+1][0], myargv[p+2][0]);
  951.         printf("Warping to Episode %s, Map %s.\n",
  952.            myargv[p+1],myargv[p+2]);
  953.         break;
  954.         
  955.       case commercial:
  956.       default:
  957.         p = atoi (myargv[p+1]);
  958.         if (p<10)
  959.           sprintf (file,"~"DEVMAPS"cdata/map0%i.wad", p);
  960.         else
  961.           sprintf (file,"~"DEVMAPS"cdata/map%i.wad", p);
  962.         break;
  963.     }
  964.     D_AddFile (file);
  965.     }
  966.     
  967.     p = M_CheckParm ("-file");
  968.     if (p)
  969.     {
  970.     // the parms after p are wadfile/lump names,
  971.     // until end of parms or another - preceded parm
  972.     modifiedgame = true;            // homebrew levels
  973.     while (++p != myargc && myargv[p][0] != '-')
  974.         D_AddFile (myargv[p]);
  975.     }
  976.  
  977.     p = M_CheckParm ("-playdemo");
  978.  
  979.     if (!p)
  980.     p = M_CheckParm ("-timedemo");
  981.  
  982.     if (p && p < myargc-1)
  983.     {
  984.     sprintf (file,"%s.lmp", myargv[p+1]);
  985.     D_AddFile (file);
  986.     printf("Playing demo %s.lmp.\n",myargv[p+1]);
  987.     }
  988.     
  989.     // get skill / episode / map from parms
  990.     startskill = sk_medium;
  991.     startepisode = 1;
  992.     startmap = 1;
  993.     autostart = false;
  994.  
  995.         
  996.     p = M_CheckParm ("-skill");
  997.     if (p && p < myargc-1)
  998.     {
  999.     startskill = myargv[p+1][0]-'1';
  1000.     autostart = true;
  1001.     }
  1002.  
  1003.     p = M_CheckParm ("-episode");
  1004.     if (p && p < myargc-1)
  1005.     {
  1006.     startepisode = myargv[p+1][0]-'0';
  1007.     startmap = 1;
  1008.     autostart = true;
  1009.     }
  1010.     
  1011.     p = M_CheckParm ("-timer");
  1012.     if (p && p < myargc-1 && deathmatch)
  1013.     {
  1014.     int     time;
  1015.     time = atoi(myargv[p+1]);
  1016.     printf("Levels will end after %d minute",time);
  1017.     if (time>1)
  1018.         printf("s");
  1019.     printf(".\n");
  1020.     }
  1021.  
  1022.     p = M_CheckParm ("-avg");
  1023.     if (p && p < myargc-1 && deathmatch)
  1024.     printf("Austin Virtual Gaming: Levels will end after 20 minutes\n");
  1025.  
  1026.     p = M_CheckParm ("-warp");
  1027.     if (p && p < myargc-1)
  1028.     {
  1029.     if (gamemode == commercial)
  1030.         startmap = atoi (myargv[p+1]);
  1031.     else
  1032.     {
  1033.         startepisode = myargv[p+1][0]-'0';
  1034.         startmap = myargv[p+2][0]-'0';
  1035.     }
  1036.     autostart = true;
  1037.     }
  1038.     
  1039.     // init subsystems
  1040.     printf ("V_Init: allocate screens.\n");
  1041.     V_Init ();
  1042.  
  1043.     printf ("M_LoadDefaults: Load system defaults.\n");
  1044.     M_LoadDefaults ();              // load before initing other systems
  1045.  
  1046.     printf ("Z_Init: Init zone memory allocation daemon. \n");
  1047.     Z_Init ();
  1048.  
  1049.     printf ("W_Init: Init WADfiles.\n");
  1050.     W_InitMultipleFiles (wadfiles);
  1051.     
  1052.  
  1053.     // Check for -file in shareware
  1054.     if (modifiedgame)
  1055.     {
  1056.     // These are the lumps that will be checked in IWAD,
  1057.     // if any one is not present, execution will be aborted.
  1058.     char name[23][8]=
  1059.     {
  1060.         "e2m1","e2m2","e2m3","e2m4","e2m5","e2m6","e2m7","e2m8","e2m9",
  1061.         "e3m1","e3m3","e3m3","e3m4","e3m5","e3m6","e3m7","e3m8","e3m9",
  1062.         "dphoof","bfgga0","heada1","cybra1","spida1d1"
  1063.     };
  1064.     int i;
  1065.     
  1066.     if ( gamemode == shareware)
  1067.         I_Error("\nYou cannot -file with the shareware "
  1068.             "version. Register!");
  1069.  
  1070.     // Check for fake IWAD with right name,
  1071.     // but w/o all the lumps of the registered version. 
  1072.     if (gamemode == registered)
  1073.         for (i = 0;i < 23; i++)
  1074.         if (W_CheckNumForName(name[i])<0)
  1075.             I_Error("\nThis is not the registered version.");
  1076.     }
  1077.     
  1078.     // Iff additonal PWAD files are used, print modified banner
  1079.     if (modifiedgame)
  1080.     {
  1081.     /*m*/printf (
  1082.         "===========================================================================\n"
  1083.         "ATTENTION:  This version of DOOM has been modified.  If you would like to\n"
  1084.         "get a copy of the original game, call 1-800-IDGAMES or see the readme file.\n"
  1085.         "        You will not receive technical support for modified games.\n"
  1086.         "                      press enter to continue\n"
  1087.         "===========================================================================\n"
  1088.         );
  1089.     getchar ();
  1090.     }
  1091.     
  1092.  
  1093.     // Check and print which version is executed.
  1094.     switch ( gamemode )
  1095.     {
  1096.       case shareware:
  1097.       case indetermined:
  1098.     printf (
  1099.         "===========================================================================\n"
  1100.         "                                Shareware!\n"
  1101.         "===========================================================================\n"
  1102.     );
  1103.     break;
  1104.       case registered:
  1105.       case retail:
  1106.       case commercial:
  1107.     printf (
  1108.         "===========================================================================\n"
  1109.         "                 Commercial product - do not distribute!\n"
  1110.         "         Please report software piracy to the SPA: 1-800-388-PIR8\n"
  1111.         "===========================================================================\n"
  1112.     );
  1113.     break;
  1114.     
  1115.       default:
  1116.     // Ouch.
  1117.     break;
  1118.     }
  1119.  
  1120.     printf ("M_Init: Init miscellaneous info.\n");
  1121.     M_Init ();
  1122.  
  1123.     printf ("R_Init: Init DOOM refresh daemon - ");
  1124.     R_Init ();
  1125.  
  1126.     printf ("\nP_Init: Init Playloop state.\n");
  1127.     P_Init ();
  1128.  
  1129.     printf ("I_Init: Setting up machine state.\n");
  1130.     I_Init ();
  1131.  
  1132.     printf ("D_CheckNetGame: Checking network game status.\n");
  1133.     D_CheckNetGame ();
  1134.  
  1135.     printf ("S_Init: Setting up sound.\n");
  1136.     S_Init (snd_SfxVolume /* *8 */, snd_MusicVolume /* *8*/ );
  1137.  
  1138.     printf ("HU_Init: Setting up heads up display.\n");
  1139.     HU_Init ();
  1140.  
  1141.     printf ("ST_Init: Init status bar.\n");
  1142.     ST_Init ();
  1143.  
  1144.     // check for a driver that wants intermission stats
  1145.     p = M_CheckParm ("-statcopy");
  1146.     if (p && p<myargc-1)
  1147.     {
  1148.     // for statistics driver
  1149.     extern  void*    statcopy;                            
  1150.  
  1151.     statcopy = (void*)atoi(myargv[p+1]);
  1152.     printf ("External statistics registered.\n");
  1153.     }
  1154.     
  1155.     // start the apropriate game based on parms
  1156.     p = M_CheckParm ("-record");
  1157.  
  1158.     if (p && p < myargc-1)
  1159.     {
  1160.     G_RecordDemo (myargv[p+1]);
  1161.     autostart = true;
  1162.     }
  1163.     
  1164.     p = M_CheckParm ("-playdemo");
  1165.     if (p && p < myargc-1)
  1166.     {
  1167.     singledemo = true;              // quit after one demo
  1168.     G_DeferedPlayDemo (myargv[p+1]);
  1169.     D_DoomLoop ();  // never returns
  1170.     }
  1171.     
  1172.     p = M_CheckParm ("-timedemo");
  1173.     if (p && p < myargc-1)
  1174.     {
  1175.     G_TimeDemo (myargv[p+1]);
  1176.     D_DoomLoop ();  // never returns
  1177.     }
  1178.     
  1179.     p = M_CheckParm ("-loadgame");
  1180.     if (p && p < myargc-1)
  1181.     {
  1182.     if (M_CheckParm("-cdrom"))
  1183.         sprintf(file, "c:\\doomdata\\"SAVEGAMENAME"%c.dsg",myargv[p+1][0]);
  1184.     else
  1185.         sprintf(file, SAVEGAMENAME"%c.dsg",myargv[p+1][0]);
  1186.     G_LoadGame (file);
  1187.     }
  1188.     
  1189.  
  1190.     if ( gameaction != ga_loadgame )
  1191.     {
  1192.     if (autostart || netgame)
  1193.         G_InitNew (startskill, startepisode, startmap);
  1194.     else
  1195.         D_StartTitle ();                // start up intro loop
  1196.  
  1197.     }
  1198.  
  1199.     D_DoomLoop ();  // never returns
  1200. }
  1201.